wayland: Add a cursor cache
authorKristian Høgsberg <krh@bitplanet.net>
Thu, 21 Mar 2013 02:34:03 +0000 (22:34 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Thu, 21 Mar 2013 02:56:50 +0000 (22:56 -0400)
We avoid creating a new GdkCursor object every time
_gdk_wayland_display_get_cursor_for_name/type() is called.

gdk/wayland/gdkcursor-wayland.c
gdk/wayland/gdkdisplay-wayland.c
gdk/wayland/gdkdisplay-wayland.h
gdk/wayland/gdkprivate-wayland.h

index ce6456515cbd0a7c0a7ea25b82facb5f3f478367..198753e1939589ce669a99efcdce72024df39c6c 100644 (file)
@@ -65,6 +65,68 @@ G_DEFINE_TYPE (GdkWaylandCursor, _gdk_wayland_cursor, GDK_TYPE_CURSOR)
 
 static guint theme_serial = 0;
 
+struct cursor_cache_key
+{
+  GdkCursorType type;
+  const char *name;
+};
+
+static void
+add_to_cache (GdkWaylandDisplay *display, GdkWaylandCursor *cursor)
+{
+  display->cursor_cache = g_slist_prepend (display->cursor_cache, cursor);
+
+  g_object_ref (cursor);
+}
+
+static gint
+cache_compare_func (gconstpointer listelem,
+                    gconstpointer target)
+{
+  GdkWaylandCursor *cursor = (GdkWaylandCursor *) listelem;
+  struct cursor_cache_key* key = (struct cursor_cache_key *) target;
+
+  if (cursor->cursor.type != key->type)
+    return 1; /* No match */
+
+  /* Elements marked as pixmap must be named cursors
+   * (since we don't store normal pixmap cursors
+   */
+  if (key->type == GDK_CURSOR_IS_PIXMAP)
+    return strcmp (key->name, cursor->name);
+
+  return 0; /* Match */
+}
+
+static GdkWaylandCursor*
+find_in_cache (GdkWaylandDisplay *display,
+               GdkCursorType      type,
+               const char        *name)
+{
+  GSList* res;
+  struct cursor_cache_key key;
+
+  key.type = type;
+  key.name = name;
+
+  res = g_slist_find_custom (display->cursor_cache, &key, cache_compare_func);
+
+  if (res)
+    return (GdkWaylandCursor *) res->data;
+
+  return NULL;
+}
+
+/* Called by gdk_wayland_display_finalize to flush any cached cursors
+ * for a dead display.
+ */
+void
+_gdk_wayland_display_finalize_cursors (GdkWaylandDisplay *display)
+{
+  g_slist_foreach (display->cursor_cache, (GFunc) g_object_unref, NULL);
+  g_slist_free (display->cursor_cache);
+}
+
 static void
 gdk_wayland_cursor_finalize (GObject *object)
 {
@@ -281,6 +343,15 @@ _gdk_wayland_display_get_cursor_for_name (GdkDisplay  *display,
 
   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
 
+  private = find_in_cache (wayland_display, GDK_CURSOR_IS_PIXMAP, name);
+  if (private)
+    {
+      /* Cache had it, add a ref for this user */
+      g_object_ref (private);
+
+      return (GdkCursor*) private;
+    }
+
   private = g_object_new (GDK_TYPE_WAYLAND_CURSOR,
                           "cursor-type", GDK_CURSOR_IS_PIXMAP,
                           "display", display,
@@ -319,6 +390,8 @@ _gdk_wayland_display_get_cursor_for_name (GdkDisplay  *display,
 
   private->buffer = wl_cursor_image_get_buffer(cursor->images[0]);
 
+  add_to_cache (wayland_display, private);
+
   return GDK_CURSOR (private);
 }
 
index e244118c3b332bff288ba93f588f3dacaf2241a9..4193d53971bfc6f242d0dfbb30cefc0ab69d8637 100644 (file)
@@ -204,6 +204,8 @@ gdk_wayland_display_finalize (GObject *object)
 {
   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (object);
 
+  _gdk_wayland_display_finalize_cursors (display_wayland);
+
   /* Keymap */
   if (display_wayland->keymap)
     g_object_unref (display_wayland->keymap);
index fb284e323c7af4b89ffb534892f5aaee082dad73..ce2082de06d4e6797eff27aa3bd21f0a3df861fc 100644 (file)
@@ -65,6 +65,7 @@ struct _GdkWaylandDisplay
   struct wl_data_device_manager *data_device_manager;
 
   struct wl_cursor_theme *cursor_theme;
+  GSList *cursor_cache;
 
   GSource *event_source;
 
index 6f07059b79aa5ae26f850072a075c2f26da64e52..480108ec46b1be376f355c5d61ebc23813429b2f 100644 (file)
@@ -53,6 +53,8 @@ GdkKeymap *_gdk_wayland_keymap_new_from_fd (uint32_t format,
                                             uint32_t fd, uint32_t size);
 struct xkb_state *_gdk_wayland_keymap_get_xkb_state (GdkKeymap *keymap);
 
+void       _gdk_wayland_display_finalize_cursors (GdkWaylandDisplay *display);
+
 GdkCursor *_gdk_wayland_display_get_cursor_for_type (GdkDisplay    *display,
                                                     GdkCursorType  cursor_type);
 GdkCursor *_gdk_wayland_display_get_cursor_for_name (GdkDisplay  *display,